home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Czech Logic, Card & Gambling Games
/
Logické hry.iso
/
hry
/
Sokoban
/
source
/
think.cpp
< prev
Wrap
C/C++ Source or Header
|
2005-09-26
|
47KB
|
1,751 lines
#include <windows.h>
#pragma hdrstop
#include <string.h>
#include <assert.h>
#include "level.h"
//---------------------------------------------------------------------------
/*
POZOR!
velikost zßsobnφku nastavte na 256MB (v Project/Settings/Linker/Output)
velikost swapovacφho souboru nastavte na 1200MB (Ovlßdacφ panely/SystΘm/Up°esnit/Mo₧nosti v²konu)
Pam∞¥
posTable: (18+Nobj)*maxPos
hashTable: 8*maxPos
movedObj: Nobj*48*maxPos
*/
struct Move {
Psquare obj,next; //odkud kam se p°esouvß
short dist; //vzdßlenost mezi hrßΦem a obj
short direct; //sm∞r p°esunu
};
typedef Move *PMove;
int DXY=1; //2 pro vφce ne₧ 256 polφ, jinak 1
int
Nobj, //poΦet objekt∙
Nstore, //poΦet ·lo₧iÜ¥
Nground, //poΦet polφΦek, kde nenφ ze∩
posSize, //dΘlka pozice bez hlaviΦky (v bytech)
posSize1, //jako posSize, ale sni₧uje se p°i testBlocked
posSize2, //alokovanß dΘlka na pozici v posTable
DHDR, //dΘlka hlaviΦky p°ed pozicφ
distId, //ka₧dΘ volßnφ findObjects pou₧ije jinΘ id
maxPos, //max. poΦet prohledßvan²ch pozic
maxPos0=5000000,//omezenφ maxPos
maxMem=900, //omezenφ adresovΘho prostroru (MB)
DhashTable, //dΘlka hashovacφ tabulky
algorithm, //0=do hloubky, 1=do Üφ°ky, 2=dijkstra, 3=gener
testing, //byl zmenÜen poΦet objekt∙ uvnit° testBlocked
finalDone, //poΦet objekt∙ na ·lo₧iÜtφch
*finalDistA;//pole pro vÜechny finalDists
Pchar
*hashTable, //hashovacφ tabulka prohledan²ch pozic
*hashTablek,//konec hashovacφ tabulky
UfoundPos, //nalezenß koncovß pozice
UfoundPosD,
posTable, //pam∞¥ na vÜechny prohledanΘ pozice
posTablek,
UposTable, //ukazatel na volnΘ mφsto v posTable
UfoundSol, //ukazatel na konec °eÜenφ
firstMove, //tahy vzniklΘ smazßnφm slep²ch uliΦek
UfirstMove,
finalPos; //koncovß pozice (bez hrßΦe)
PMove
movedObj; //pam∞¥ pro Move
Psquare
*distBuf1,*distBuf2, //pomocnΘ buffery pro findDist a findObjects
*i2p, //p°evod Φφsla polφΦka na ukazatel
*fin2p; //ukazatele na ·lo₧iÜt∞ (v po°adφ, v jakΘm se zaplnφ)
//hlaviΦka pozice p°i prohledßvßnφ do hloubky
struct Hdr2 {
Pchar parent;
int eval;
PMove lastMove;
short dist;
};
const int DHDR2= 14;
//hlaviΦka pozice p°i prohledßvßnφ do Üφ°ky
struct Hdr3 {
Pchar parent;
short mov,pus;
PMove movesBeg,movesEnd;
bool dual;
};
const int DHDR3= 17;
//hlaviΦka pozice p°i Dijkstrov∞ algoritmu
struct Hdr1 {
Pchar parent;
int eval;
int heapItem;
PMove lastMove;
bool dual;
};
const int DHDR1= 17;
//hlaviΦka pozice p°i generovßnφ zadßnφ
struct Hdr4 {
short mov,pus;
PMove movesBeg,movesEnd;
};
const int DHDR4= 12;
typedef Hdr1 *PHdr1;
typedef Hdr2 *PHdr2;
typedef Hdr3 *PHdr3;
typedef Hdr4 *PHdr4;
#define HDR1(p) ((Hdr1*)(p-DHDR1))
#define HDR2(p) ((Hdr2*)(p-DHDR2))
#define HDR3(p) ((Hdr3*)(p-DHDR3))
#define HDR4(p) ((Hdr4*)(p-DHDR4))
Pchar backtrack(PMove Umoves, int movpus) ;
//-------------------------------------------------------------------
inline void wrXY0(Pchar p, int i)
{
if(DXY==1) *((BYTE*)p) = (BYTE)i;
else *((WORD*)p) = (WORD)i;
}
inline void wrXY(Pchar &p, int i)
{
if(DXY==1) *((BYTE*)p) = (BYTE)i, p++;
else *((WORD*)p) = (WORD)i, p+=2;
}
inline int rdXY(void *p)
{
if(DXY==1) return *((BYTE*)p);
else return *((WORD*)p);
}
void noMem()
{
msg(lng(768,"Not enough memory"));
}
//-------------------------------------------------------------------
//nalezenφ nejkratÜφ cesty mezi src a dest (bez p°esunu beden)
//do polφ zapφÜe hodnoty dist, distId
void findDist(Psquare src, Psquare dest)
{
int i,d;
Psquare *p1,*p2,pn;
distId++;
src->distId=distId;
src->dist=0;
distBuf1[0]=src;
distBuf1[1]=0;
for(d=1; ; d++){
if(d&1) p1=distBuf1,p2=distBuf2;
else p1=distBuf2,p2=distBuf1;
if(!*p1) break;
for( ; *p1; p1++){
for(i=0; i<4; i++){
pn= nxtP(*p1,i);
if(pn->distId!=distId){
if(pn->obj==BM_GROUND){
pn->distId=distId;
pn->dist=d;
*p2++=pn;
}else{
pn->dist=MAXDIST;
}
}
}
if(*p1==dest) return;
}
*p2=0;
}
}
//-------------------------------------------------------------------
#ifndef NDEBUG
int testPos(Pchar prevPos)
{
Pchar v;
int i;
Psquare p;
for(v=prevPos+DXY; v<prevPos+posSize1; v+=DXY){
i=rdXY(v);
for(p=board; p->i!=i || p->obj!=BM_OBJECT; p++){
if(p==boardk){
return 0;
}
}
}
for(v=prevPos+2*DXY; v<prevPos+posSize1; v+=DXY){
if(rdXY(v)<=rdXY(v-DXY)) return 0;
}
return 1;
}
#endif
//-------------------------------------------------------------------
#define finOrWall(p) ((p)->obj!=BM_WALL && !(p)->store)
int testDead(Psquare p)
{
Psquare pU,pD,pU2,pD2;
pU=nxtP(p,2); pU2=nxtP(pU,2);
pD=nxtP(p,3); pD2=nxtP(pD,3);
if((p+1)->obj!=BM_GROUND){
if(pD->obj!=BM_GROUND){
if((pD+1)->obj!=BM_GROUND)
if(!p->store || finOrWall(p+1) || finOrWall(pD) || finOrWall(pD+1)) return 1;
if((pD+2)->obj!=BM_GROUND && (pD2+1)->obj!=BM_GROUND && (pD2+2)->obj!=BM_GROUND)
if(!(pD+1)->store && !p->store) return 1;
}else{
if((pD2)->obj!=BM_GROUND){
if((pD-1)->obj!=BM_GROUND &&
(pD+1)->obj!=BM_GROUND && (pD2-1)->obj!=BM_GROUND
|| (pD2+1)->obj!=BM_GROUND && (pD-1)->obj==BM_WALL &&
(pD+2)->obj==BM_WALL && !(pD+1)->store)
if(!(pD)->store && !p->store) return 1;
}
}
if(pU->obj!=BM_GROUND){
if((pU+1)->obj!=BM_GROUND)
if(!p->store || finOrWall(p+1) || finOrWall(pU) || finOrWall(pU+1)) return 1;
if((pU+2)->obj!=BM_GROUND && (pU2+1)->obj!=BM_GROUND && (pU2+2)->obj!=BM_GROUND)
if(!(pU+1)->store && !p->store) return 1;
}else{
if((pU2)->obj!=BM_GROUND){
if((pU+1)->obj!=BM_GROUND &&
(pU-1)->obj!=BM_GROUND && (pU2-1)->obj!=BM_GROUND
|| (pU2+1)->obj!=BM_GROUND && (pU-1)->obj==BM_WALL &&
(pU+2)->obj==BM_WALL && !(pU+1)->store)
if(!(pU)->store && !p->store) return 1;
}
}
}else{
if((p+2)->obj!=BM_GROUND){
if(((pD)->obj!=BM_GROUND && (pD+2)->obj!=BM_GROUND &&
(pU+1)->obj==BM_WALL && (pD2+1)->obj==BM_WALL && !(pD+1)->store
|| (pU)->obj!=BM_GROUND && (pU+2)->obj!=BM_GROUND &&
(pD+1)->obj==BM_WALL && (pU2+1)->obj==BM_WALL && !(pU+1)->store)
|| (pU+1)->obj!=BM_GROUND && (pD+1)->obj!=BM_GROUND &&
((pU)->obj!=BM_GROUND && (pD+2)->obj!=BM_GROUND ||
(pD)->obj!=BM_GROUND && (pU+2)->obj!=BM_GROUND))
if(!(p+1)->store && !p->store) return 1;
}
}
if((p-1)->obj!=BM_GROUND){
if(pD->obj!=BM_GROUND){
if((pD-1)->obj!=BM_GROUND)
if(!p->store || finOrWall(p-1) || finOrWall(pD) || finOrWall(pD-1)) return 1;
if((pD-2)->obj!=BM_GROUND && (pD2-1)->obj!=BM_GROUND && (pD2-2)->obj!=BM_GROUND)
if(!(pD-1)->store && !p->store) return 1;
}else{
if((pD2)->obj!=BM_GROUND){
if((pD+1)->obj!=BM_GROUND &&
(pD-1)->obj!=BM_GROUND && (pD2+1)->obj!=BM_GROUND
|| (pD2-1)->obj!=BM_GROUND && (pD+1)->obj==BM_WALL &&
(pD-2)->obj==BM_WALL && !(pD-1)->store)
if(!(pD)->store && !p->store) return 1;
}
}
if(pU->obj!=BM_GROUND){
if((pU-1)->obj!=BM_GROUND)
if(!p->store || finOrWall(p-1) || finOrWall(pU) || finOrWall(pU-1)) return 1;
if((pU-2)->obj!=BM_GROUND && (pU2-1)->obj!=BM_GROUND && (pU2-2)->obj!=BM_GROUND)
if(!(pU-1)->store && !p->store) return 1;
}else{
if((pU2)->obj!=BM_GROUND){
if((pU+1)->obj!=BM_GROUND &&
(pU-1)->obj!=BM_GROUND && (pU2+1)->obj!=BM_GROUND
|| (pU2-1)->obj!=BM_GROUND && (pU+1)->obj==BM_WALL &&
(pU-2)->obj==BM_WALL && !(pU-1)->store)
if(!(pU)->store && !p->store) return 1;
}
}
}else{
if((p-2)->obj!=BM_GROUND){
if(((pD)->obj!=BM_GROUND && (pD-2)->obj!=BM_GROUND &&
(pU-1)->obj==BM_WALL && (pD2-1)->obj==BM_WALL && !(pD-1)->store
|| (pU)->obj!=BM_GROUND && (pU-2)->obj!=BM_GROUND &&
(pD-1)->obj==BM_WALL && (pU2-1)->obj==BM_WALL && !(pU-1)->store)
|| (pU-1)->obj!=BM_GROUND && (pD-1)->obj!=BM_GROUND &&
((pU)->obj!=BM_GROUND && (pD-2)->obj!=BM_GROUND ||
(pD)->obj!=BM_GROUND && (pU-2)->obj!=BM_GROUND))
if(!(p-1)->store && !p->store) return 1;
}
}
return 0;
}
//-------------------------------------------------------------------
//nalezenφ dosa₧iteln²ch objekt∙ a vygenerovßnφ tah∙
PMove findObjects(PMove Umoves)
{
Psquare pn,pnn,*p1,*p2;
int i,d;
distId++;
mover->distId=distId;
mover->dist=0;
distBuf1[0]=mover;
distBuf1[1]=0;
for(d=1; ; d++){
if(d&1) p1=distBuf1,p2=distBuf2;
else p1=distBuf2,p2=distBuf1;
if(!*p1) break;
for( ; *p1; p1++){
for(i=0; i<4; i++){
pn= nxtP(*p1,i);
if(pn->distId!=distId && pn->obj==BM_GROUND){
pn->distId=distId;
pn->dist=d;
*p2++=pn;
}
else if(pn->obj==BM_OBJECT){
pnn= nxtP(pn,i);
if(pnn->obj==BM_GROUND && pnn->finalDist<MAXDIST){
Umoves->obj=pn;
Umoves->next=pnn;
Umoves->dist=(short)d;
Umoves->direct=(short)i;
Umoves++;
}
}
}
}
*p2=0;
}
return Umoves;
}
//-------------------------------------------------------------------
PMove findObjectsR(PMove Umoves)
{
Psquare pn,pnn,*p1,*p2;
int i,d;
distId++;
mover->distId=distId;
mover->dist=0;
distBuf1[0]=mover;
distBuf1[1]=0;
for(d=1; ; d++){
if(d&1) p1=distBuf1,p2=distBuf2;
else p1=distBuf2,p2=distBuf1;
if(!*p1) break;
for( ; *p1; p1++){
for(i=0; i<4; i++){
pn= nxtP(*p1,i);
if(pn->distId!=distId && pn->obj==BM_GROUND){
pn->distId=distId;
pn->dist=d;
*p2++=pn;
}
else if(pn->obj==BM_OBJECT){
pnn= prvP(*p1,i);
if(pnn->obj==BM_GROUND){
Umoves->obj=pn;
Umoves->next=*p1;
Umoves->dist=(short)d;
Umoves->direct=(short)i;
Umoves++;
}
}
}
}
*p2=0;
}
return Umoves;
}
//-------------------------------------------------------------------
PMove findObjectsD(PMove Umoves, Psquare o, int dir)
{
Psquare pn,pnn,*p1,*p2;
int i,d;
bool found;
distId++;
mover->distId=distId;
mover->dist=0;
distBuf1[0]=mover;
distBuf1[1]=0;
for(d=1; ; d++){
if(d&1) p1=distBuf1,p2=distBuf2;
else p1=distBuf2,p2=distBuf1;
if(!*p1) break;
for( ; *p1; p1++){
found=false;
for(i=0; i<4; i++){
pn= nxtP(*p1,i);
if(pn->distId!=distId && pn->obj==BM_GROUND){
pn->distId=distId;
pn->dist=d;
*p2++=pn;
}
else if(pn->obj==BM_OBJECT){
pnn= prvP(*p1,i);
if(pnn->obj==BM_GROUND){
found=true;
}
}
}
if(found){
Umoves->next=*p1;
Umoves->dist=(short)d;
Umoves->obj=o;
Umoves->direct=(short)dir;
Umoves++;
}
}
*p2=0;
}
return Umoves;
}
//-------------------------------------------------------------------
void makeMove(Pchar newPos, Pchar prevPos, Move &curMove)
{
Pchar v,v1;
memcpy(newPos,prevPos,posSize);
//nalezni posledn∞ p°esunut² objekt
for(v=newPos+DXY; rdXY(v)!=curMove.obj->i; v+=DXY) ;
//set°id pozici
if(curMove.next->i < curMove.obj->i){
for(v1=v-DXY; rdXY(v1)>curMove.next->i && v1>newPos; v1-=DXY){
wrXY0(v1+DXY,rdXY(v1));
}
wrXY0(v1+DXY,curMove.next->i);
}
else{
for(v1=v+DXY; v1<newPos+posSize1 && rdXY(v1)<curMove.next->i; v1+=DXY){
wrXY0(v1-DXY,rdXY(v1));
}
wrXY0(v1-DXY,curMove.next->i);
}
//pozice hrßΦe
wrXY0(newPos,curMove.obj->i);
assert(testPos(newPos));
}
//-------------------------------------------------------------------
//v²poΦet hashovacφ funkce
Pchar *hash(Pchar pos)
{
DWORD h;
Pchar posEnd;
h=0;
posEnd= pos+posSize1;
for( ; pos<posEnd; pos++){
h= (h + (DWORD)*(Puchar)pos)*1234567;
// h= h = (h << 5) + h + *(Puchar)pos;
}
return &hashTable[h%DhashTable];
}
//-------------------------------------------------------------------
//p°ed touto funkcφ musφ b²t zavolßno findObjects
int testBlocked(Pchar prevPos, PMove lastMove, PMove Umoves)
{
Psquare p,p0,pn,*p1,*p2;
Pchar curPos,v1,v2,found,w;
int i,d,posSize0,result,finalDone0;
if(!lastMove) return 0;
//podφvej se okolo poslednφho tahu
p0=lastMove->next;
p1=distBuf1;
for(i=0; i<8; i++){
p=nxtP(p0,i);
if(p->obj==BM_GROUND && p->distId!=distId){
*p1++=p;
p->distId=distId+1;
}
}
if(p1-distBuf1==0) return 0;
if(UposTable==posTablek) return 0;
*p1=0;
//najdi objekty sousedφcφ s nedosa₧itelnou oblastφ
distId++;
for(d=1; ; d++){
if(d&1) p1=distBuf1,p2=distBuf2;
else p1=distBuf2,p2=distBuf1;
if(!*p1) break;
for( ; *p1; p1++){
for(i=0; i<8; i++){
pn= nxtP(*p1,i);
if(pn->distId!=distId){
if(pn->obj==BM_OBJECT){
pn->distId=distId;
}
else if(pn->obj==BM_GROUND && i<4){
pn->distId=distId;
*p2++=pn;
}
}
}
}
*p2=0;
}
//testovacφ pozice zapisuj od konce alokovanΘ pam∞ti
if(!testing){
w=posTablek;
posTablek=UposTable-posSize2;
UposTable= w-posSize2;
posSize2= -posSize2;
}
//vytvo° novou pozici, kterß mß mΘn∞ objekt∙
curPos= UposTable;
v2=curPos+DXY;
for(v1=prevPos+DXY; v1<prevPos+posSize1; v1+=DXY){
p=i2p[rdXY(v1)];
if(p->distId==distId){
wrXY(v2,p->i);
}else{
p->obj=BM_GROUND;
#ifdef DEBUG
paintSquare(p);
#endif
}
}
//sni₧ posSize1
posSize0=posSize1;
posSize1=(int)(v2-curPos);
result=0;
if(posSize1<posSize0){
if(posSize1>2*DXY){
while(v2!=curPos+posSize){
wrXY(v2,-1);
}
//spus¥ backtracking
HDR2(curPos)->parent=0;
HDR2(curPos)->eval=0;
HDR2(curPos)->lastMove=0;
finalDone0=finalDone;
testing++;
#ifdef DEBUG
repaint();
Sleep(10);
#endif
found= backtrack(Umoves,0);
if(found){
HDR2(found)->parent=curPos;
}else{
//pozice je ne°eÜitelnß nebo moc slo₧itß
result=1;
}
testing--;
finalDone=finalDone0;
}
//vra¥ zpßtky vÜechny objekty
posSize1=posSize0;
for(v1=prevPos+DXY; v1<prevPos+posSize1; v1+=DXY){
assert(rdXY(v1)>=0 && rdXY(v1)<width*height);
i2p[rdXY(v1)]->obj=BM_OBJECT;
#ifdef DEBUG
paintSquare(i2p[rdXY(v1)]);
#endif
}
}
if(!testing){
posSize2= -posSize2;
w=posTablek;
posTablek=UposTable+posSize2;
UposTable= w+posSize2;
}
return result;
}
//-------------------------------------------------------------------
/*
p°φklad cont pro direct==1
. X X X X X X X X
-1 0 1 1 2 0 1 1 X
. X X X . X X X X
*/
//protlaΦenφ objektu zkrz celou chodbu
PMove testLastMove(PMove lastMove, PMove Umoves)
{
if(lastMove && lastMove->next->cont[lastMove->direct]>0){
Psquare p=nxtP(lastMove->next, lastMove->direct);
if(p->obj==BM_GROUND && p->finalDist<MAXDIST){
//tlaΦenφ objektu ve stejnΘm sm∞ru jako p°edchozφ tah
Umoves->obj= lastMove->next;
Umoves->next= p;
Umoves->dist=1;
Umoves->direct= lastMove->direct;
Umoves++;
}
return Umoves;
}
return 0;
}
PMove testLastMoveR(PMove lastMove, PMove Umoves)
{
if(lastMove && lastMove->next->cont[lastMove->direct^1]==1){
Psquare p=prvP(lastMove->next, lastMove->direct);
Psquare pn=prvP(p,lastMove->direct);
assert(p->obj==BM_GROUND);
assert(lastMove->obj->obj==BM_GROUND);
assert(lastMove->next->obj==BM_OBJECT);
if(pn->obj==BM_GROUND){
//ta₧enφ objektu ve stejnΘm sm∞ru jako p°edchozφ tah
Umoves->obj= lastMove->next;
Umoves->next= p;
Umoves->dist=1;
Umoves->direct= lastMove->direct;
Umoves++;
}
return Umoves;
}
return 0;
}
void testLastMoveD(PMove lastMove, PMove Umoves, PMove UmovesEnd)
{
if(!lastMove) return;
Psquare pm= prvP(lastMove->obj,lastMove->direct);
if(pm->cont[lastMove->direct^1]==1){
Psquare p=prvP(pm, lastMove->direct);
assert(p->obj==BM_GROUND);
assert(lastMove->obj->obj==BM_GROUND);
assert(pm->obj==BM_OBJECT);
for(PMove m=Umoves; m<UmovesEnd; m++){
if(m->obj!=pm || m->direct!=lastMove->direct) m->direct=-1;
}
}
}
//-------------------------------------------------------------------
Pchar backtrack(PMove Umoves, int movpus)
{
Pchar *u,v,newPos,prevPos,found,result=0;
int m,o,i,f1,f2,movpus1,finalDone0,direct0;
PMove UmovesEnd,um,bm;
Psquare mover0,*newMover,p,pn;
Move curMove;
prevPos=UposTable;
mover0=mover;
finalDone0=finalDone;
//najdi dosa₧itelnΘ objekty
UmovesEnd= findObjects(Umoves);
//hrßΦe umφsti do levΘho hornφho rohu
for(newMover=i2p; (*newMover)->distId!=distId; newMover++) ;
//do pozice zapiÜ polohu hrßΦe
wrXY0(prevPos,(*newMover)->i);
//ukonΦi testBlocked jakmile se lze dostat k objekt∙m ze vÜech stran
if(testing){
for(v=prevPos+posSize1-DXY; v>prevPos; v-=DXY){
p=i2p[rdXY(v)];
if(!p->store){
for(i=0; i<4; i++){
pn=nxtP(p,i);
if(pn->obj==BM_GROUND && pn->distId!=distId) goto l1;
}
}
}
return prevPos;
}
l1:
//vypoΦti hashovacφ funkci
u= hash(prevPos);
//p°idej novou pozici do tabulky
for( ;*u; ){
if(!memcmp(*u,prevPos,posSize)){
if(testing && HDR2(*u)->parent){
//pozice je °eÜitelnß
return *u;
}
//neprohledßvej stejnou pozici vφcekrßt
return 0;
}
u++;
if(u==hashTablek) u=hashTable;
}
*u=prevPos;
UposTable+=posSize2;
//protlaΦ objekt celou chodbou
um=testLastMove(HDR2(prevPos)->lastMove, Umoves);
if(um) UmovesEnd=um;
//zjisti, jestli poslednφ tah n∞co nezablokoval
if(testBlocked(prevPos, HDR2(prevPos)->lastMove, UmovesEnd)) return 0;
//vyzkouÜej postupn∞ vÜechny mo₧nΘ p°esuny
for( ; Umoves<UmovesEnd; Umoves++){
newPos=UposTable;
if(newPos==posTablek) break; //pam∞¥ u₧ je plnß
bm=Umoves;
if(0+testing){
//zvol p°esun sm∞rem do zablokovanΘho prostoru
m=-1;
for(um=Umoves; um<UmovesEnd; um++){
for(i=0; i<4; i++){
p=nxtP(um->obj,i);
if(p->obj==BM_GROUND && distId - p->distId > m){
m = distId - p->distId;
bm=um;
}
}
}
}else{
//vyber objekt, kter² je nejblφ₧e ·lo₧iÜti
m=0x7fffffff;
for(um=Umoves; um<UmovesEnd; um++){
f1= um->obj->finalDists[finalDone];
f2= um->next->finalDists[finalDone];
o= (f2<<2) + ((f2-f1)<<5) + um->dist;
if(um->obj->direct == (um->direct^1)) o+=600;
if(o<m){
m=o;
bm=um;
}
}
}
curMove=*bm;
*bm=*Umoves;
movpus1= movpus+curMove.dist+1;
//prove∩ jeden p°esun
curMove.next->obj= BM_OBJECT;
curMove.obj->obj= BM_GROUND;
if(testDead(curMove.next)){
curMove.next->obj= BM_GROUND;
curMove.obj->obj= BM_OBJECT;
}else{
#ifdef DEBUG
mover=0;
paintSquare(curMove.next);
paintSquare(curMove.obj);
Sleep(20);
#endif
mover=curMove.obj;
direct0= curMove.next->direct;
curMove.next->direct= curMove.direct;
//vytvo° novou pozici
HDR2(newPos)->parent=0;
HDR2(newPos)->eval= movpus1;
HDR2(newPos)->lastMove= &curMove;
makeMove(newPos,prevPos,curMove);
//porovnej novou pozici s koncovou pozicφ
amax(finalDone, curMove.obj->finalDist);
if(curMove.next->finalDist==finalDone){
do{
finalDone++;
}while(fin2p[finalDone]->obj==BM_OBJECT);
}
if(!testing && finalDone==Nstore){
UfoundPos= newPos;
HDR2(newPos)->eval=movpus1;
HDR2(newPos)->parent=prevPos;
UposTable+=posSize2;
result=prevPos;
}else{
//backtracking
found=backtrack(UmovesEnd, movpus1);
if(found){
HDR2(found)->parent= prevPos;
assert(testing || HDR2(found)->eval==movpus1);
HDR2(found)->dist= (short) (curMove.dist+1);
result=prevPos;
}
}
//vra¥ zp∞t vÜechny zm∞ny
curMove.next->obj= BM_GROUND;
curMove.obj->obj= BM_OBJECT;
#ifdef DEBUG
mover=0;
paintSquare(curMove.next);
paintSquare(curMove.obj);
#endif
curMove.next->direct= direct0;
mover=mover0;
finalDone=finalDone0;
if(result) break;
}
}
return result;
}
//-------------------------------------------------------------------
void depthSearch()
{
int m=mover->i;
//p°iprav poΦßteΦnφ pozici
PHdr2 hdr= HDR2(UposTable);
hdr->parent=0;
hdr->eval=0;
hdr->lastMove=0;
while(fin2p[finalDone]->obj==BM_OBJECT) finalDone++;
//spus¥ backtracking
backtrack(movedObj,0);
//obnov poΦßteΦnφ pozici hrßΦe
wrXY0(posTable+DHDR2, m);
}
//-------------------------------------------------------------------
void breadthSearch()
{
Pchar *u,v,curPos,newPos;
char *movedObjBeg,*m;
PHdr3 curPosHdr,newPosHdr,found;
PMove Umoves,Umoves1,um;
Psquare p,pn,*pp;
int i,j;
bool isDual;
//poΦßteΦnφ pozice
curPos=UposTable;
curPosHdr=HDR3(curPos);
curPosHdr->parent=0;
curPosHdr->mov=curPosHdr->pus=0;
curPosHdr->movesBeg= movedObj;
curPosHdr->movesEnd= Umoves= findObjects(movedObj);
curPosHdr->dual= false;
UposTable+=posSize2;
///
/*
memcpy(posTable+posSize2,posTable,posSize2);
findDist(i2p[rdXY(posTable+DHDR)],0);
for(pp=i2p; (*pp)->distId!=distId; pp++) ;
wrXY0(UposTable,(*pp)->i);
newPosHdr=HDR3(UposTable);
newPosHdr->mov=(short)(*pp)->dist;
u=hash(UposTable);
assert(!*u);
*u=UposTable;
UposTable+=posSize2;
*/
//sma₧ vÜechny objekty
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_OBJECT);
i2p[rdXY(v)]->obj=BM_GROUND;
}
//koncovß pozice
for(i=0; i<Nstore; i++){
assert(fin2p[i]->obj==BM_GROUND);
fin2p[i]->obj=BM_OBJECT;
}
///curPos=UposTable;
//vφce koncov²ch pozic podle umφst∞nφ hrßΦe
for(p=board; p<boardk; p++){
p->distId=0;
}
for(j=0; j<Nstore; j++){
p=fin2p[j];
for(i=0; i<4; i++){
pn=nxtP(p,i);
if(!pn->distId && pn->obj==BM_GROUND){
findDist(pn,0);
for(pp=i2p; (*pp)->distId!=distId; pp++) ;
memcpy(UposTable+DXY,finalPos,posSize1-DXY);
wrXY0(UposTable,(*pp)->i);
UposTable+=posSize2;
}
}
}
for(v=curPos+posSize2; v<UposTable; v+=posSize2){
newPosHdr=HDR3(v);
newPosHdr->parent=0;
newPosHdr->mov=curPosHdr->pus=0;
newPosHdr->dual= true;
newPosHdr->movesBeg= Umoves;
mover=i2p[rdXY(v)];
newPosHdr->movesEnd= findObjectsR(Umoves);
///
for(um=Umoves; um<newPosHdr->movesEnd; um++) um->dist=1;
Umoves= newPosHdr->movesEnd;
}
//sma₧ vÜechny objekty
for(i=0; i<Nstore; i++){
assert(fin2p[i]->obj==BM_OBJECT);
fin2p[i]->obj=BM_GROUND;
}
movedObjBeg=(char*)movedObj+65536;
//cyklus p°es vÜechny nalezenΘ pozice
for( ;curPos<UposTable; curPos+=posSize2){
curPosHdr= HDR3(curPos);
isDual= curPosHdr->dual;
//vytvo° aktußlnφ pozici
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_GROUND);
i2p[rdXY(v)]->obj=BM_OBJECT;
}
//uvolni tahy, kterΘ u₧ byly zpracovßny
m= (char*)( (int)curPosHdr->movesBeg & -65536 );
i= m-movedObjBeg;
if(i>5000000){
VirtualFree(movedObjBeg,i,MEM_DECOMMIT);
movedObjBeg=m;
}
//vyzkouÜej vÜechny mo₧nΘ p°esuny
for(Umoves1=curPosHdr->movesBeg; Umoves1<curPosHdr->movesEnd && Umoves1->direct>=0; Umoves1++){
Move &curMove= *Umoves1;
newPos=UposTable;
if(newPos==posTablek) break;
newPosHdr=HDR3(newPos);
//prove∩ tah
assert(testPos(curPos));
assert(curMove.next->obj==BM_GROUND);
assert(curMove.obj->obj==BM_OBJECT);
curMove.next->obj= BM_OBJECT;
curMove.obj->obj= BM_GROUND;
if(isDual || !testDead(curMove.next)){
//vytvo° novou pozici
mover= isDual ? prvP(curMove.next,curMove.direct) : curMove.obj;
makeMove(newPos,curPos,curMove);
newPosHdr->mov= (short)(curPosHdr->mov + curMove.dist);
newPosHdr->pus= (short)(curPosHdr->pus + 1);
newPosHdr->dual= isDual;
//najdi vÜechny mo₧nΘ p°esuny v novΘ pozici
newPosHdr->movesEnd= isDual ? findObjectsR(Umoves) : findObjects(Umoves);
//hrßΦe dej do levΘho hornφho rohu
for(pp=i2p; (*pp)->distId!=distId; pp++) ;
wrXY0(newPos,(*pp)->i);
//vypoΦti hashovacφ funkci
u=hash(newPos);
for(;;){
if(!*u){
//p°idej novou pozici do tabulky
*u=newPos;
UposTable+=posSize2;
newPosHdr->parent= curPos;
newPosHdr->movesBeg= Umoves;
if(1 || !isDual){ ///
um= (isDual ? testLastMoveR:testLastMove)(&curMove, Umoves);
if(um) um->direct=-1;
}
if(!isDual && testBlocked(newPos, &curMove, newPosHdr->movesEnd)){///
//pozice nebude mφt ₧ßdnΘ tahy
newPosHdr->movesEnd= Umoves;
}else{
Umoves= newPosHdr->movesEnd;
}
#ifdef DEBUG
repaint();
Sleep(1);
#endif
break;
}
if(!memcmp(*u,newPos,posSize)){
//pozice byla v tabulce nalezena
found=HDR3(*u);
if(found->dual!=isDual){
newPosHdr->parent= curPos;
if(isDual){
UfoundPos=*u;
UfoundPosD=newPos;
}else{
UfoundPosD=*u;
UfoundPos=newPos;
}
return;
}
if(found->pus == newPosHdr->pus &&
found->mov > newPosHdr->mov){
//nalezeno lepÜφ °eÜenφ
found->mov= newPosHdr->mov;
found->parent= curPos;
if(found->movesEnd > found->movesBeg){
assert(newPosHdr->movesEnd-Umoves==found->movesEnd-found->movesBeg);
memcpy(found->movesBeg,Umoves,(char*)newPosHdr->movesEnd-(char*)Umoves);
}
}
break;
}
u++;
if(u==hashTablek) u=hashTable;
}
}
//vra¥ tah zp∞t
curMove.next->obj= BM_GROUND;
curMove.obj->obj= BM_OBJECT;
}
//sma₧ vÜechny objekty
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_OBJECT);
i2p[rdXY(v)]->obj=BM_GROUND;
}
if(UposTable==posTablek) break; //pam∞¥ u₧ je plnß
}
}
//-------------------------------------------------------------------
void addToHash(Pchar pos)
{
Pchar *u;
u=hash(pos);
while(*u){
u++;
if(u==hashTablek) u=hashTable;
}
*u=pos;
}
//-------------------------------------------------------------------
void dijkstra()
{
int i,j,heapSize,foundEval,movpus1,x;
Pchar *u,v,curPos,newPos;
PHdr1 curPosHdr,newPosHdr,*heap,h;
PMove Umoves,UmovesEnd,um;
Psquare p,pn,pr,pnn;
bool isDual;
foundEval=0x7fffffff;
//halda obsahuje ukazatele na pozice
heap= new PHdr1[maxPos];
//poΦßteΦnφ pozice
curPos=UposTable;
heap[curPosHdr->heapItem=heapSize=1]= curPosHdr= HDR1(curPos);
curPosHdr->parent=0;
curPosHdr->eval=0;
curPosHdr->lastMove=0;
curPosHdr->dual=false;
addToHash(UposTable);
UposTable+=posSize2;
//sma₧ vÜechny objekty
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_OBJECT);
i2p[rdXY(v)]->obj=BM_GROUND;
}
//vφce koncov²ch pozic - vedle ka₧dΘho objektu
for(j=0; j<Nstore; j++){
p=fin2p[j];
for(i=0; i<4; i++){
pn=nxtP(p,i);
if(pn->obj==BM_GROUND && !pn->store){
pnn=nxtP(pn,i);
if(pnn->obj==BM_GROUND && !pnn->store){
memcpy(UposTable+DXY,finalPos,posSize1-DXY);
wrXY0(UposTable,pn->i);
h= HDR1(UposTable);
heap[h->heapItem=++heapSize]=h;
h->parent=0;
h->eval=0;
h->lastMove=0;
h->dual=true;
addToHash(UposTable);
UposTable+=posSize2;
}
}
}
}
Umoves=movedObj;
//cyklus p°es vÜechny nalezenΘ pozice
for( ;heapSize; ){
//vezmi vrchol heapu - pozice s nejmenÜφm moves+pushes
curPosHdr= heap[1];
curPosHdr->heapItem=0;
curPos= ((Pchar)curPosHdr)+DHDR1;
isDual= curPosHdr->dual;
//odstra≥ vrchol heapu
x=heap[heapSize]->eval;
j=1;
i=2;
while(i<heapSize){
if(i+1 < heapSize && heap[i]->eval > heap[i+1]->eval) i++;
if(x <= heap[i]->eval) break;
heap[j]=heap[i];
heap[j]->heapItem=j;
j=i;
i*=2;
}
heap[j]=heap[heapSize];
heap[j]->heapItem=j;
heapSize--;
//vytvo° aktußlnφ pozici
mover= i2p[rdXY(curPos)];
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_GROUND);
i2p[rdXY(v)]->obj=BM_OBJECT;
}
if(curPos==UfoundPos || curPos==UfoundPosD) goto end;
//najdi vÜechny mo₧nΘ p°esuny v aktußlnφ pozici
if(!isDual){
UmovesEnd=findObjects(Umoves);
}else{
UmovesEnd=Umoves;
p=mover;
for(i=0; i<4; i++){
pn=nxtP(p,i);
if(pn->obj==BM_OBJECT){
pr=prvP(p,i);
if(pr->obj==BM_GROUND){
mover=pr;
p->obj=BM_OBJECT;
pn->obj=BM_GROUND;
UmovesEnd=findObjectsD(UmovesEnd,pn,i);
pn->obj=BM_OBJECT;
p->obj=BM_GROUND;
}
}
}
mover=p;
}
if(!isDual){
um= testLastMove(curPosHdr->lastMove, Umoves);
if(um) UmovesEnd=um;
}else{
testLastMoveD(curPosHdr->lastMove,Umoves,UmovesEnd);
}
if(1 || !testBlocked(curPos, curPosHdr->lastMove, UmovesEnd)){
for(; Umoves<UmovesEnd; Umoves++){
newPos=UposTable;
if(newPos==posTablek) break;
newPosHdr=HDR1(newPos);
assert(testPos(curPos));
//prove∩ tah
Move &curMove= *Umoves;
if(curMove.direct<0) continue;
assert(curMove.obj->obj==BM_OBJECT);
curMove.obj->obj= BM_GROUND;
mover= curMove.obj;
if(isDual){
mover= curMove.next;
curMove.next= prvP(curMove.obj,curMove.direct);
}
assert(curMove.next->obj==BM_GROUND);
curMove.next->obj= BM_OBJECT;
if(isDual || !testDead(curMove.next)){
//vytvo° novou pozici
makeMove(newPos,curPos,curMove);
wrXY0(newPos,mover->i);
movpus1= curPosHdr->eval + curMove.dist + 1;
//vypoΦti hashovacφ funkci
u=hash(newPos);
for(;;){
if(!*u){
//p°idej novou pozici do tabulky
*u=newPos;
newPosHdr->dual=isDual;
UposTable+=posSize2;
//zv∞tÜi velikost heapu
newPosHdr->heapItem= ++heapSize;
#ifdef DEBUG
repaint();
Sleep(1);
#endif
break;
}
if(rdXY(*u)==rdXY(newPos) && !memcmp(*u,newPos,posSize)){
//pozice byla v tabulce nalezena
h=HDR1(*u);
//test setkßnφ dop°ednΘho a dußlnφho °eÜenφ
if(h->dual!=isDual){
if(!h->heapItem && movpus1+h->eval < foundEval){///
foundEval= movpus1+h->eval;
if(isDual){
UfoundPos=*u;
UfoundPosD=curPos;
}else{
UfoundPosD=*u;
UfoundPos=curPos;
}
}
goto nxt;
}
newPos=*u;
newPosHdr= HDR1(newPos);
assert(!newPosHdr->parent || newPosHdr->parent>=posTable && newPosHdr->parent<posTablek);
if(newPosHdr->eval <= movpus1) goto nxt;
//nalezeno lepÜφ °eÜenφ
break;
}
u++;
if(u==hashTablek) u=hashTable;
}
//oprav set°φd∞nφ heapu
newPosHdr->parent= curPos;
newPosHdr->eval= movpus1;
newPosHdr->lastMove= &curMove;
j= newPosHdr->heapItem;
i=j/2;
while(i>0 && heap[i]->eval > movpus1){
heap[j]=heap[i];
heap[j]->heapItem=j;
j=i;
i/=2;
}
heap[j]= newPosHdr;
newPosHdr->heapItem=j;
}
nxt:
//vra¥ tah zp∞t
curMove.next->obj= BM_GROUND;
curMove.obj->obj= BM_OBJECT;
}
}
//sma₧ vÜechny objekty
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_OBJECT);
i2p[rdXY(v)]->obj=BM_GROUND;
}
if(UposTable==posTablek) break;
}
end:
delete[] heap;
if(UfoundPos){
}
}
//-------------------------------------------------------------------
void delBlind()
{
Psquare p,pn,pn1;
int i,j,i1;
//sma₧ slepΘ uliΦky
UfirstMove= firstMove= new char[width*height/2];
for(p=board; p<boardk; p++){
if(p->obj==BM_GROUND && !p->store){
j=0;
for(i=0; i<4; i++){
pn=nxtP(p,i);
if(pn->obj!=BM_WALL){
j++;
pn1=pn;
i1=i;
}
}
if(j==1){
if(p==mover){
if(pn1->obj==BM_OBJECT){
if(nxtP(pn1,i1)->obj!=BM_GROUND || pn1->store){
continue;
}
pn1->obj=BM_GROUND;
nxtP(pn1,i1)->obj=BM_OBJECT;
*UfirstMove++ = char('4'+i1);
}else{
*UfirstMove++ = char('0'+i1);
}
mover=pn1;
}
p->obj=BM_WALL;
p=board;
}
}
}
}
//-------------------------------------------------------------------
int thinkInit()
{
Psquare p,pn,pnn,*p1,*p2,*pf,*ps,po[4];
int i,j,jm,m,d,k,w,*UfinA,*finRadius;
Pchar UfinalPos,UstartPos;
Nobj=Nstore=i=0;
for(p=board; p<boardk; p++){
if(p->obj==BM_GROUND || p->obj==BM_OBJECT){
p->i=i++;
for(j=0; j<4; j++){
po[j]=nxtP(p,j);
p->cont[j]=-1;
}
if(po[0]->obj!=BM_WALL && po[1]->obj!=BM_WALL &&
po[2]->obj==BM_WALL && po[3]->obj==BM_WALL){
p->cont[0]=p->cont[1]=1;
}
else if(po[0]->obj==BM_WALL && po[1]->obj==BM_WALL &&
po[2]->obj!=BM_WALL && po[3]->obj!=BM_WALL){
p->cont[2]=p->cont[3]=1;
}
}else{
p->i=-1;
}
if(p->obj==BM_OBJECT) Nobj++;
if(p->store) Nstore++;
p->distId=0;
}
Nground=i;
UfinA= finalDistA= new int[i*Nstore];
i2p= new Psquare[i];
fin2p= new Psquare[Nstore+1];
DXY=1;
if(i>255) DXY=sizeof(WORD);
if(Nobj) maxPos= maxMem*1000000/4/sizeof(Move)/Nstore;
aminmax(maxPos,100,maxPos0);
const int D[]={DHDR2,DHDR3,DHDR1,DHDR4};
DHDR= D[algorithm];
distId=0;
posSize1= posSize= (Nobj+1)*DXY;
posSize2= posSize1+DHDR;
DhashTable= maxPos*2+17;
hashTable= new char*[DhashTable];
hashTablek= hashTable+DhashTable;
posTable= new char[maxPos*posSize2];
UposTable= posTable+DHDR;
posTablek= UposTable + maxPos*posSize2;
UfoundPos=UfoundPosD=0;
testing=0;
finalDone=0;
if(!posTable){
noMem();
movedObj=0;
finalPos=0;
return 1;
}
memset(hashTable,0,DhashTable*sizeof(*hashTable));
//poΦßteΦnφ a koncovß pozice
UfinalPos= finalPos= new char[Nstore*DXY];
p1=distBuf1;
p2=distBuf2;
UstartPos= UposTable;
wrXY(UstartPos, mover->i);
pf=fin2p;
for(p=board; p<boardk; p++){
p->finalDist=MAXDIST;
if(p->store){
p->finalDist=0;
*p1++=p;
*p2++=p;
*pf++=p;
wrXY(UfinalPos,p->i);
}
if(p->obj==BM_OBJECT){
wrXY(UstartPos,p->i);
}
if(p->i!=-1){
i2p[p->i]=p;
p->finalDists= UfinA;
UfinA += Nstore;
p->direct=-1;
for(j=0; j<4; j++){
if((prvP(p,j)->cont[j]&-2)==0 &&
p->cont[j]==-1 && !p->store &&
(nxtP(p,j^2)->obj==BM_WALL || nxtP(p,j^3)->obj==BM_WALL)){
p->cont[j]=2;
}
if(p->cont[j]==1 &&
(p->store || (prvP(p,j)->cont[j]&-2))){
p->cont[j]=0;
}
}
}
}
assert(UfinA==finalDistA+Nground*Nstore);
//po°adφ koncov²ch polφΦek
*p1=*p2=0;
ps=distBuf2;
for(d=Nstore; *ps && d>=0; d--){
for(p1=ps; *p1; p1++){
for(i=0; i<4; i++){
pn= nxtP(*p1,i);
pnn= nxtP(pn,i);
if(pn->obj!=BM_WALL && pnn->obj!=BM_WALL &&
pn->finalDist>d && pnn->finalDist>d){
(*p1)->finalDist=d;
*p1=*ps++;
break;
}
}
}
}
//v²poΦet finalDist
for(d=(Nstore+1)|1; ; d++){
if(d&1) p1=distBuf1,p2=distBuf2;
else p1=distBuf2,p2=distBuf1;
if(!*p1) break;
for( ; *p1; p1++){
for(i=0; i<4; i++){
pn= nxtP(*p1,i);
pnn= nxtP(pn,i);
if(pn->finalDist>=MAXDIST && pn->obj!=BM_WALL && pnn->obj!=BM_WALL
&& pn->obj!=BM_BACKGROUND){
pn->finalDist=d;
*p2++=pn;
}
}
}
*p2=0;
}
//vypoΦti finalDists[j]
for(p1=fin2p; p1<fin2p+Nstore; p1++){
(*p1)->finalDist=0;
}
finRadius= new int[Nstore];
for(k=Nstore; k; ){
for(j=0; j<k; j++){
for(p1=i2p; p1<i2p+Nground; p1++){
(*p1)->finalDists[j]=MAXDIST;
}
p=fin2p[j];
distBuf1[0]=p;
distBuf1[1]=0;
p->finalDists[j]=0;
for(d=(Nstore+1)|1; ; d++){
if(d&1) p1=distBuf1,p2=distBuf2;
else p1=distBuf2,p2=distBuf1;
if(!*p1) break;
for( ; *p1; p1++){
for(i=0; i<4; i++){
pn= nxtP(*p1,i);
pnn= nxtP(pn,i);
if(pn->obj!=BM_WALL && pn->obj!=BM_BACKGROUND &&
pn->finalDists[j]>=MAXDIST &&
pnn->obj!=BM_WALL &&
pn->finalDist>=k && pnn->finalDist>=k){
pn->finalDists[j]=d;
*p2++=pn;
}
}
}
*p2=0;
}
finRadius[j]=d;
}
m=MAXDIST;
jm=0;
for(j=0; j<k; j++){
if(finRadius[j]<=m && finRadius[j] > Nstore+5 &&
(finRadius[j]<m || k==Nstore ||
fin2p[k]->finalDists[j] < fin2p[k]->finalDists[jm])){
m=finRadius[j];
jm=j;
}
}
k--;
p=fin2p[jm];
fin2p[jm]=fin2p[k];
fin2p[k]=p;
p->finalDist=k;
for(p1=i2p; p1<i2p+Nground; p1++){
p=*p1;
w= p->finalDists[k];
p->finalDists[k]= p->finalDists[jm];
p->finalDists[jm]= w;
if(p->finalDist<k) p->finalDists[k]=0;
}
}
fin2p[Nstore]= board;
delete[] finRadius;
assert(testPos(UposTable));
if(!memcmp(finalPos,UposTable+DXY,posSize1-DXY)){
UfoundPos=UfoundPosD=UposTable;
}
movedObj= new Move[Nobj*4*maxPos];
if(!movedObj){
noMem();
return 1;
}
return 0;
}
//-------------------------------------------------------------------
void thinkDestroy()
{
delete[] movedObj;
delete[] finalPos;
delete[] posTable;
delete[] hashTable;
delete[] fin2p;
delete[] i2p;
delete[] finalDistA;
delete[] firstMove; firstMove=0;
}
//-------------------------------------------------------------------
void gener()
{
Pchar *u,v,curPos,newPos;
PHdr4 curPosHdr,newPosHdr;
PMove Umoves,Umoves1;
Psquare *pp;
algorithm=3;
if(thinkInit()){
thinkDestroy();
return;
}
curPos= UposTable;
curPosHdr=HDR4(curPos);
curPosHdr->mov=curPosHdr->pus=0;
curPosHdr->movesBeg= movedObj;
curPosHdr->movesEnd= Umoves= findObjectsR(movedObj);
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_OBJECT);
i2p[rdXY(v)]->obj=BM_GROUND;
}
UposTable+=posSize2;
for( ;curPos<UposTable; curPos+=posSize2){
curPosHdr= HDR4(curPos);
//vytvo° aktußlnφ pozici
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_GROUND);
i2p[rdXY(v)]->obj=BM_OBJECT;
}
for(Umoves1=curPosHdr->movesBeg; Umoves1<curPosHdr->movesEnd; Umoves1++){
Move &curMove= *Umoves1;
newPos=UposTable;
if(newPos==posTablek) break;
newPosHdr=HDR4(newPos);
//prove∩ tah
assert(testPos(curPos));
assert(curMove.next->obj==BM_GROUND);
assert(curMove.obj->obj==BM_OBJECT);
curMove.next->obj= BM_OBJECT;
curMove.obj->obj= BM_GROUND;
//vytvo° novou pozici
mover= prvP(curMove.next,curMove.direct);
//najdi vÜechny mo₧nΘ p°esuny v novΘ pozici
newPosHdr->movesEnd= findObjectsR(Umoves);
if(newPosHdr->movesEnd>Umoves){
makeMove(newPos,curPos,curMove);
newPosHdr->mov= (short)(curPosHdr->mov + curMove.dist);
newPosHdr->pus= (short)(curPosHdr->pus + 1);
//hrßΦe dej do levΘho hornφho rohu
for(pp=i2p; (*pp)->distId!=distId; pp++) ;
wrXY0(newPos,(*pp)->i);
//vypoΦti hashovacφ funkci
u=hash(newPos);
for(;;){
if(!*u){
//p°idej novou pozici do tabulky
*u=newPos;
UposTable+=posSize2;
newPosHdr->movesBeg= Umoves;
Umoves= newPosHdr->movesEnd;
#ifdef DEBUG
repaint();
#endif
break;
}
if(!memcmp(*u,newPos,posSize1)){
//pozice byla v tabulce nalezena
break;
}
u++;
if(u==hashTablek) u=hashTable;
}
}
//vra¥ tah zp∞t
curMove.next->obj= BM_GROUND;
curMove.obj->obj= BM_OBJECT;
}
//sma₧ vÜechny objekty
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
assert(i2p[rdXY(v)]->obj==BM_OBJECT);
i2p[rdXY(v)]->obj=BM_GROUND;
}
}
//nastav poslednφ nalezenou pozici
curPos=UposTable-posSize2;
curPosHdr=HDR4(curPos);
mover= i2p[rdXY(curPos)];
for(v=curPos+DXY; v<curPos+posSize1; v+=DXY){
i2p[rdXY(v)]->obj=BM_OBJECT;
}
repaint();
msg("%d-%d\n%d", curPosHdr->mov, curPosHdr->pus,
(UposTable-posTable)/posSize2);
thinkDestroy();
edUndo=edRec; edRedo=0;
}
//-------------------------------------------------------------------
//p°emφsti se ze src na dest
void wrSolPath(Psquare src, Psquare dest)
{
Psquare p,pn;
int i;
if(!src) return;
findDist(dest,src);
assert(src->distId==distId);
for(p=src; p!=dest; p=pn){
for(i=0; ; i++){
pn=nxtP(p,i);
if(pn->dist==p->dist-1) break;
}
*UfoundSol++= (char) (i+'0');
}
}
//-------------------------------------------------------------------
Pchar getParent(Pchar pos)
{
switch(algorithm){
case 0:
return HDR2(pos)->parent;
case 1:
return HDR3(pos)->parent;
case 2:
return HDR1(pos)->parent;
}
return 0;
}
//-------------------------------------------------------------------
void wrSol()
{
Pchar u,prv,v,v1,v2,foundSol;
Psquare p,pn,moverS=0;
int d,direct,dual;
//zapiÜ tahy vzniklΘ smazßnφm slep²ch uliΦek
logPos=logbuf;
for(u=firstMove; u<UfirstMove; u++){
wrLog(*u);
}
//alokuj buffer pro v²sledek
switch(algorithm){
case 0:
d=HDR2(UfoundPos)->eval;
break;
case 1:
d=HDR3(UfoundPos)->mov+HDR3(UfoundPosD)->mov+Nground;
break;
case 2:
d=HDR1(UfoundPos)->eval+HDR1(UfoundPosD)->eval+Nground;
break;
}
foundSol= new char[d+1];
for(dual=0; dual<2; dual++){
UfoundSol=foundSol;
//sma₧ objekty
for(p=board; p<boardk; p++){
if(p->obj==BM_OBJECT) p->obj=BM_GROUND;
}
//nastav pozici
u= dual ? UfoundPosD:UfoundPos;
if(!u) break;
for(v=u+DXY; v<u+posSize1; v+=DXY){
i2p[rdXY(v)]->obj=BM_OBJECT;
}
mover=0;
if(dual) mover=moverS;
//projdi pozice sm∞rem k poΦßteΦnφ nebo koncovΘ
for(; (prv=getParent(u))!=0; u=prv){
//zjisti sm∞r p°esunu mezi pozicemi prv, u
for(v1=prv+DXY,v2=u+DXY; rdXY(v1)==rdXY(v2); v1+=DXY,v2+=DXY) ;
d= rdXY(v2)-rdXY(v1);
if(d>0){
if(d!=1 || v1+DXY<prv+posSize1 && rdXY(v1+DXY)==rdXY(v2)){
direct=2;
}else{
direct=0;
}
p=i2p[rdXY(v1)];
pn=prvP(p,direct);
if(pn->obj!=BM_OBJECT){
assert(direct==0 && pn->obj==BM_WALL);
pn=prvP(p,direct=2);
}
}else{
if(d!=-1 || v2+DXY<u+posSize1 && rdXY(v1)==rdXY(v2+DXY)){
direct=3;
}else{
direct=1;
}
pn=i2p[rdXY(v2)];
p=nxtP(pn,direct);
if(p->obj!=BM_GROUND){
assert(direct==1);
p=nxtP(pn,direct=3);
}
}
//p°emφsti se k objektu
wrSolPath(mover, dual ? prvP(pn,direct) : p);
if(u==UfoundPos) moverS=p;
//prove∩ p°esun z pn na p
assert(pn->obj==BM_OBJECT);
assert(p->obj==BM_GROUND);
pn->obj=BM_GROUND;
p->obj=BM_OBJECT;
mover= dual ? pn : nxtP(p,direct);
*UfoundSol++= (char) (direct+'4');
}
if(!dual){
wrSolPath(mover, i2p[rdXY(posTable+DHDR)]);
//prvnφ polovina °eÜenφ - obrßcen∞
for(u=UfoundSol-1; u>=foundSol; u--){
wrLog(char(*u^1));
}
if(algorithm==2){
HDR1(UfoundPos)->parent=UfoundPosD;
UfoundPosD=UfoundPos;
}
}else{
//druhß polovina °eÜenφ
for(u=foundSol; u<UfoundSol; u++){
wrLog(*u);
}
}
}
delete[] foundSol;
*logPos=0;
logPos=0;
}
//-------------------------------------------------------------------
int findSolution(int alg)
{
int k;
DWORD time= GetTickCount();
algorithm=alg;
delBlind();
if(thinkInit()){
thinkDestroy();
return -4;
}
if(Nobj!=Nstore || !Nobj) return -3;
switch(algorithm){
case 0:
depthSearch();
break;
case 1:
breadthSearch();
break;
case 2:
dijkstra();
break;
}
assert(UposTable<=posTablek);
if(UfoundPos){
//zapiÜ a "zkomprimuj" °eÜenφ
wrSol();
///assert(algorithm!=2 || mov+pus==HDR1(UfoundPos)->eval);
//if(algorithm==1) msg("%d-%d, %d-%d",HDR3(UfoundPos)->mov,HDR3(UfoundPos)->pus,HDR3(UfoundPosD)->mov,HDR3(UfoundPosD)->pus);
}
thinkDestroy();
time=GetTickCount()-time;
if(UfoundPos){
loadSolution(level, logbuf);
assert(!movError);
//zapsßnφ °eÜenφ do databßze
finish();
saveUser();
saveData();
status();
if(gratulOn){
k= int(((char*)UposTable-(char*)posTable)/posSize2);
msg("Solution: %d-%d\nTime: %d ms\n\nPositions: %d, %d",
moves,pushes, time, k, maxPos - int(((char*)posTablek-(char*)UposTable)/posSize2) - k);
}
return moves+pushes;
}else{
resetLevel();
}
if(UposTable==posTablek){
if(gratulOn){
k= int((char*)UposTable-(char*)posTable)/posSize2;
msg("Timeout: %d ms\n\nPositions: %u, %u",
time, k, maxPos - k);
}
return -1;
}
msg("Unsolvable");
return -2;
}
//-------------------------------------------------------------------